package main

import (
	"context"
	"fmt"
	"reflect"
	"strconv"
	"sync"
	"time"
)

type people struct {
	name string
	age  int
}

func (p people) walk() {
	fmt.Println(p.name + "is walking")
}

type man struct {
	people
}

type Icar interface {
	Driver()
}

type Suv struct {
}

func (s Suv) Driver() {
	fmt.Println("suv Driver")
}

func human(icar Icar) {
	icar.Driver()
}

var wg sync.WaitGroup

func w(n int) {
	fmt.Println(n)
	wg.Done()
}

func refFun(f func(a int, b int) int) (int, error) {
	v := reflect.ValueOf(f)
	if v.Kind() != reflect.Func {
		return 0, nil
	}
	args := make([]reflect.Value, 2)
	args[0] = reflect.ValueOf(0)
	args[1] = reflect.ValueOf(1)
	res := v.Call(args)
	return res[0].Interface().(int), nil
}

// channel 实现锁
type myMutex chan struct{}

func (m myMutex) NewMyMutex() myMutex {
	return make(chan struct{}, 1)
}
func (m myMutex) clock() {
	m <- struct{}{}
}

func (m myMutex) unclock() {
	<-m
}

type Demo struct {
	name string
}

var once sync.Once

var demo *Demo

func GetDemo(name string) *Demo {

	if demo == nil {
		once.Do(func() {
			demo = &Demo{
				name: name,
			}
		})
	}
	return demo
}

var ch1 = make(chan struct{}, 1)
var ch2 = make(chan struct{}, 1)
var wg1 sync.WaitGroup

func p1() {

	for i := 0; i < 3; i++ {
		<-ch1
		fmt.Println(i)
		ch2 <- struct{}{}
	}
	wg1.Done()

}

func p2() {
	str := "abcdefg"
	for i := 0; i < 3; i++ {
		<-ch2
		fmt.Println(string(str[i]))
		ch1 <- struct{}{}
	}
	wg1.Done()
}

func getNum() (ref int) {
	defer func() {
		ref++
	}()
	return 10
}

func getN(a int, b int) int {
	sum := a + b
	defer func() {
		sum++
	}()
	return sum
}

func p() {
	panic("error")

	defer func() {
		e := recover()
		if e != nil {
			fmt.Println(e)
		}
	}()
}

func main() {

	p()
	return
	ref := getN(1, 2)
	fmt.Println(ref)

	n := getNum()
	fmt.Println(n)
	return

	i := new(int)
	s := new(string)
	i2 := new([]int)
	fmt.Println(i2)
	fmt.Println(s)
	fmt.Println(i)
	return
	numbers := []int{1, 2, 3, 4, 5}

	for _, value := range numbers {
		fmt.Printf("Address: %p, Value: %d\n", &value, value)
	}
	return
	var m1 map[int]string
	m := make(map[int]string, 0)
	fmt.Println(m1 == nil)
	fmt.Println(m == nil)
	for i, _ := range m {
		fmt.Println(m[i])
	}
	return
	a1 := "nnnabc"
	for _, v := range a1 {
		fmt.Printf("%P\n", &v)
	}
	return

	wg1.Add(2)
	ch1 <- struct{}{}
	go p1()
	go p2()
	wg1.Wait()
	return

	str := "我哦哈哈"
	fmt.Println(string([]rune(str)[:2]))

	ints := make([]int, 10)
	fmt.Println(ints)

	return

	ctx, cancelFunc := context.WithCancel(context.Background())
	ctx1 := context.WithValue(ctx, "123", "aaa")
	go func(ctx2 context.Context) {
		fmt.Println(ctx2.Value("123"))
		for {
			select {
			case <-ctx2.Done():
				fmt.Println("ctx done")
				return
			default:
				fmt.Println("go on")
				time.Sleep(time.Second)
			}
		}
	}(ctx1)
	time.Sleep(2 * time.Second)
	cancelFunc()
	time.Sleep(2 * time.Second)
	fmt.Println("done")
	return
	suv := Suv{}
	icar := Icar(&suv)
	icar.Driver()

	return
	var myMutex myMutex
	mutex := myMutex.NewMyMutex()
	mutex.clock()
	mutex.unclock()

	return
	ch1 := make(chan int, 5)
	ch2 := make(chan int)
	select {
	case n := <-ch1:
		fmt.Println(n)
	case <-ch2:
		fmt.Println(1)
	default:
		fmt.Println("default")

	}

	for i2 := range ch1 {
		fmt.Println(i2)
	}
	return

	ch := make(chan int, 0)
	//go func() {
	//}()

	go func() {
		<-ch
	}()
	ch <- 0

	return
	fun, err := refFun(func(a int, b int) int {
		return a + b
	})
	if err != nil {
		return
	}

	fmt.Println(fun)
	return

	a := 123

	fmt.Println(reflect.ValueOf(a).Interface().(int))

	return
	num := 4
	wg.Add(num)
	for i := 0; i < num; i++ {
		go func(n int) {
			w(n)
		}(i)
	}
	wg.Wait()

	wg.Add(2)
	for i := 0; i < 2; i++ {
		go func(i int) {
			fmt.Println("第二个wg" + strconv.Itoa(i))
			wg.Done()
		}(i)
	}
	wg.Wait()

	//var a int
	//var b int8
	//fmt.Println(reflect.TypeOf(a))
	//fmt.Println(reflect.TypeOf(b).Kind())
	//s := Suv{}
	//human(s)

	//m := man{}
	//m.walk()

	//str := "haha嘿嘿"
	//fmt.Println(string([]rune(str)[:4]))
	//
	//ints := make([]int, 2)
	//fmt.Println(cap(ints))
	//fmt.Printf("%p\n", ints)
	//n := 1
	//for i := range ints {
	//	ints[i] = n
	//	n++
	//}
	//fmt.Println(ints)
	//ints1 := append(ints, 1, 3)
	//fmt.Println(cap(ints1))
	//fmt.Printf("%p\n", ints1)

}
